
#include "scene/entity.h"
#include "scene/scenenode.h"
#include "scene/aabb.h"

namespace engine {

	namespace scene {
	
		SceneNode::SceneNode() {
			
		}
		
		SceneNode::~SceneNode() {
			
		}
		
		const uint SceneNode::getNumAttachedObjects() const {
			return m_Objects.size();
		}
		
		bool SceneNode::attachObject(shared_ptr<Entity> newObject) {
			m_Objects[newObject->getName()] = newObject;
			return true;
		}
		
		void SceneNode::detachObject(const string& name) {
			m_Objects.erase(name);
		}
		
		void SceneNode::detachAllObjects() {
			m_Objects.clear();
		}
		
		///Return an attached object by name
		shared_ptr<Entity> SceneNode::getAttachedObject(const string& name) {
			assert(m_Objects.find(name) != m_Objects.end());
			return m_Objects[name];
		}
		
		///Return the position of this node
		const slVec3 SceneNode::getPosition() const {
			return slVec3(	m_Transform.m_Mat[12], 
							m_Transform.m_Mat[13],
							m_Transform.m_Mat[14] );
		}
		
		///Set the position of this scene node
		void SceneNode::setPosition(const slVec3& vec) {
			m_Transform.m_Mat[12] = vec.m_X;
			m_Transform.m_Mat[13] = vec.m_Y;
			m_Transform.m_Mat[14] = vec.m_Z;
		}
		
		/// Create a new child scene node with name and position 
		/// of vec relative to the parent
		shared_ptr<SceneNode> SceneNode::createChildSceneNode(const string& name, slVec3 vec) {
			shared_ptr<SceneNode> sceneNode(new SceneNode());
			sceneNode->setPosition(vec);
			
			m_Children.push_back(sceneNode);
			
			return sceneNode;
		}
		
		void SceneNode::translate(const slVec3& vec) {
			m_Transform.m_Mat[12] += vec.m_X;
			m_Transform.m_Mat[13] += vec.m_Y;
			m_Transform.m_Mat[14] += vec.m_Z;	
		}
		
		void SceneNode::scale(const slVec3& vec) {
			m_Transform.m_Mat[0] = vec.m_X;
			m_Transform.m_Mat[5] = vec.m_Y;
			m_Transform.m_Mat[10] = vec.m_Z;
		}
		
		void SceneNode::rotate(const slVec3& vec) {
			slMat4 x, y, z;
			slMat4RotationX(&x, vec.m_X);
			slMat4RotationY(&y, vec.m_Y);
			slMat4RotationZ(&z, vec.m_Z);
			assert(0); //Continue this			
		}
		
		const AABB& SceneNode::getBounds() const {
			return m_Bounds;
		}
		
		void SceneNode::updateBounds() {
			
		}
	}
}
